/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "gmock/gmock-actions.h"
#include "mockcpp/mockcpp.hpp"
#include "ObjectStorageBackupJob.h"
#include "common/CommonStruct.h"
#include "common/PrefixInfo.h"
#include "interface/CloudServiceResponse.h"
#include "interface/CloudServiceRequest.h"
#include "JsonFileTool.h"

using namespace OBSPlugin;
using namespace Module;
class ObjectStorageMultiNodeBackupTest : public testing::Test {
public:
    void SetUp() {};
    void TearDown()
    {
        GlobalMockObject::verify();
    };
};

static void ReturnVoidStub(ActionResult& returnValue, const SubJobDetails& jobInfo)
{
    returnValue.code = 0;
    return;
}

static bool QueryPreviousCopyStub(ObjectStorageBackupJob *backupJob, Copy& lastCopy)
{
    BackupObjectInfosInCopy backupObjectInfosInCopy;
    backupObjectInfosInCopy.advParms.m_aggregateSwitch = "true";
    backupObjectInfosInCopy.advParms.m_isBackupAcl = "true";
    std::vector<PrefixInfo> prefix_esn1 {
            {"bucket1", "/opt/aa", {}, true},
            {"bucket2", "/opt/aa", {"11/44"}, false}
    };
    BackupObjectInfo obj1;
    obj1.esn = "esn1";
    obj1.prefixInfo = std::move(prefix_esn1);
    backupObjectInfosInCopy.objectInfos.emplace_back(obj1);
    Module::JsonHelper::StructToJsonString(backupObjectInfosInCopy, lastCopy.extendInfo);
    return true;
}

static bool ListBucketObjectsByDepthStub(ObjectStorageBackupJob *backupJob, const std::string& bucketName,
    std::string& prefix, OBSPlugin::PrefixInfo& prefixInfo)
{
    prefixInfo.isPrefixLevelObject = true;
    prefixInfo.subPrefixs = {"11/22"};
    return true;
}

static OBSResult ListObjectsStub(Module::HWCloudService *cloudService,
    const std::unique_ptr<ListObjectsRequest>& request,
    std::unique_ptr<ListObjectsResponse>& resp)
{
    resp = std::make_unique<ListObjectsResponse>();
    resp->isTruncated = false;
    resp->nextMarker = "";
    resp->commonPrefixes = {"11/22", "33/44"};
    ListObjectsContent objContent;
    resp->contents.push_back(objContent);
    OBSResult ret;
    return ret;
}


/*
 * 用例名称：获取上一次副本信息
 * 前置条件：无
 * check点：获取上一次副本信息成功
 */
TEST_F(ObjectStorageMultiNodeBackupTest, QueryPreviousCopySuccess)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "1236565";
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    MOCKER_CPP(&JobService::ReportJobDetails)
            .stubs()
            .will(invoke(ReturnVoidStub));
    MOCKER_CPP(JobService::QueryPreviousCopy)
            .stubs()
            .will(ignoreReturnValue());
    Copy lasCopy;
    EXPECT_EQ(backupjob.QueryPreviousCopy(lasCopy), true);
}

/*
 * 用例名称：获取Bucekt前缀信息,包含层级对象
 * 前置条件：无
 * check点：判断是否返回2个前缀信息
 */
TEST_F(ObjectStorageMultiNodeBackupTest, ListBucketPrefixsSuccess)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "TEST1";
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();

    MOCKER_CPP(&ObjectStorageBackupJob::ListBucketObjectsByDepth)
            .stubs()
            .will(invoke(ListBucketObjectsByDepthStub));
    OBSPlugin::OBSProtectSubObject subObject{"bucket1", {"opt/aa"}};
    backupjob.m_protectedOBS.obsProtectSubObjectList.push_back(subObject);
    std::vector<PrefixInfo> bucketPrefix;
    EXPECT_EQ(backupjob.ListBucketPrefixs(bucketPrefix), true);
    int prefixSize = 2;
    EXPECT_EQ(bucketPrefix.size(), prefixSize);
}

/*
 * 用例名称：分层获取对象
 * 前置条件：无
 * check点：判断是否分层扫描是否成功
 */
TEST_F(ObjectStorageMultiNodeBackupTest, LevelListObjectSuccess)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "XXXXX";
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    backupjob.m_authInfo.storageType = std::to_string((int)Module::StorageType::HUAWEI);
    backupjob.InitCloudClient();
    StorageVerifyInfo verifyInfo;
    Module::HWCloudService cloudService(verifyInfo, obs_auth_switch::OBS_S3_TYPE);
    MOCKER_CPP_VIRTUAL(cloudService, &HWCloudService::ListObjects)
                    .stubs()
                    .will(invoke(ListObjectsStub));
    backupjob.m_protectedOBS.advParms.m_prefixSplitDepth = "1";
    backupjob.m_protectedOBS.advParms.m_prefixSplitter = "/";
    std::vector<PrefixInfo> bucketPrefix;
    std::deque<std::string> levelPrefixQueue;
    levelPrefixQueue.push_back("opt/aa");
    PrefixInfo prefixInfo;
    EXPECT_EQ(backupjob.LevelListObject("bucket1", 1, levelPrefixQueue, prefixInfo), true);
}


/*
 * 用例名称：获取指定对象的前缀信息
 * 前置条件：无
 * check点：判断是否分层扫描是否成功
 */
TEST_F(ObjectStorageMultiNodeBackupTest, ListBucketObjectsByDepthSUCCESS)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "1234567";
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    backupjob.m_authInfo.storageType = std::to_string((int)Module::StorageType::HUAWEI);
    backupjob.InitCloudClient();
    StorageVerifyInfo verifyInfo;
    Module::HWCloudService cloudService(verifyInfo, obs_auth_switch::OBS_S3_TYPE);
    MOCKER_CPP_VIRTUAL(cloudService, &HWCloudService::ListObjects)
                    .stubs()
                    .will(invoke(ListObjectsStub));
    backupjob.m_protectedOBS.advParms.m_prefixSplitDepth = "2";
    backupjob.m_protectedOBS.advParms.m_prefixSplitter = "/";
    PrefixInfo prefixInfo;
    std::string prefix = "opt/aa";
    EXPECT_EQ(backupjob.ListBucketObjectsByDepth("bucket1", prefix, prefixInfo), true);
}

/*
 * 用例名称：构造上一个副本元数据信息
 * 前置条件：无
 * check点：判断是否获取元数据成功
 */
TEST_F(ObjectStorageMultiNodeBackupTest, BuildLastCopyExtendInfoSUCCESS)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "45648781";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    MOCKER_CPP(&JobService::ReportJobDetails)
            .stubs()
            .will(invoke(ReturnVoidStub));
    MOCKER_CPP(&ObjectStorageBackupJob::QueryPreviousCopy)
            .stubs()
            .will(invoke(QueryPreviousCopyStub));

    std::vector<BackupObjectInfo> backupObjectInfo;
    EXPECT_EQ(backupjob.BuildLastCopyExtendInfo(backupObjectInfo), true);
   
    data->jobParam.backupType = AppProtect::BackupJobType::INCREMENT_BACKUP;
    EXPECT_EQ(backupjob.BuildLastCopyExtendInfo(backupObjectInfo), true);
}

TEST_F(ObjectStorageMultiNodeBackupTest, CreateSubJobFromBackupObjectInfo)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "45648781";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    MOCKER_CPP(&OBSPlugin::ObjectStorageBackupJob::CreateSubTask,
        int(OBSPlugin::ObjectStorageBackupJob::*)(const SubJob&))
        .stubs()
        .will(returnValue(Module::SUCCESS));

    std::vector<BackupObjectInfo> backupObjectInfos;
    std::vector<PrefixInfo> prefix_esn1 {
            {"bucket1", "/opt/aa", {}, true},
            {"bucket2", "/opt/aa", {"11/44"}, false}
    };
    BackupObjectInfo obj1;
    obj1.esn = "esn1";
    obj1.prefixInfo = std::move(prefix_esn1);
    backupObjectInfos.emplace_back(obj1);
    EXPECT_EQ(backupjob.CreateSubJobFromBackupObjectInfo(backupObjectInfos), Module::SUCCESS);
}

TEST_F(ObjectStorageMultiNodeBackupTest, GetStorageStatusExtend)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "123456";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    backupjob.m_protectedOBS.advParms.m_multiNodeBackupSwitch = "true";
    backupjob.m_protectedOBS.advParms.m_continueOnFailedSwitch = "true";
    std::string extend = backupjob.GetStorageStatusExtend(ObsErrorCode::ERROR_BACKUP_FAILED_NOSPACE_ERROR);
    EXPECT_EQ(extend.empty(), false);
}

TEST_F(ObjectStorageMultiNodeBackupTest, UpdateStorageGeneralResources)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "123456";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    MOCKER_CPP(&ShareResource::UpdateResource)
            .stubs()
            .will(ignoreReturnValue());
    StorageGeneralInfo generalInfo;
    bool ret = backupjob.UpdateStorageGeneralResources("123", generalInfo);
    EXPECT_EQ(ret, true);
}

TEST_F(ObjectStorageMultiNodeBackupTest, CheckSubJobNeedSwitchStorage)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "XXXXX";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    StorageGeneralInfo storageGeneralInfo;
    storageGeneralInfo.storageStatus = {
        {"false", "esn1"}, {"false", "esn2"}};
    EXPECT_EQ(backupjob.CheckSubJobNeedSwitchStorage("esn1", storageGeneralInfo), false);
    EXPECT_EQ(backupjob.CheckSubJobNeedSwitchStorage("esn3", storageGeneralInfo), false);
}

TEST_F(ObjectStorageMultiNodeBackupTest, ReallocateSubJob)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "5675687";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    MOCKER_CPP(&ObjectStorageBackupJob::WriteBackupObjectInfoToFile)
            .stubs()
            .will(returnValue(true));
    ObjectStorageBackupSubJob backupSubJob;
    backupSubJob.esn = "esn1";

    std::vector<PrefixInfo> prefix_esn1 {
            {"bucket1", "/opt/aa", {}, true},
            {"bucket2", "/opt/aa", {"11/44"}, false}
    };
    std::vector<PrefixInfo> prefix_esn2 {
            {"bucket2", "/opt/bb", {}, true},
            {"bucket4", "/home/aa", {"test1/test2"}, false},
            {"bucket3", "/home/aa", {"test1/test2"}, false}
    };
    BackupObjectInfosInCopy backupObjectInfosInCopy;
    BackupObjectInfo obj1;
    obj1.esn = "esn1";
    obj1.prefixInfo = std::move(prefix_esn1);
    backupObjectInfosInCopy.objectInfos.emplace_back(obj1);

    BackupObjectInfo obj2;
    obj2.esn = "esn2";
    obj2.prefixInfo = std::move(prefix_esn2);
    backupObjectInfosInCopy.objectInfos.emplace_back(obj2);
    EXPECT_EQ(backupjob.ReallocateSubJob(backupSubJob, backupObjectInfosInCopy), true);
    EXPECT_EQ(backupSubJob.esn, "esn2");
}

TEST_F(ObjectStorageMultiNodeBackupTest, CheckAndGetObjectInfo)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "XXXXX";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    MOCKER(JsonFileTool::ReadFromFile<OBSPlugin::BackupObjectInfosInCopy>)
        .stubs()
        .will(returnValue(true));
    MOCKER_CPP(&ShareResource::UpdateResource)
        .stubs()
        .will(ignoreReturnValue());
    std::vector<PrefixInfo> prefix_esn1 {
            {"bucket1", "/opt/aa", {}, true},
            {"bucket2", "/opt/aa", {"11/44"}, false}
    };
    std::vector<PrefixInfo> prefix_esn2 {
            {"bucket2", "/opt/bb", {}, true},
            {"bucket4", "/home/aa", {"test1/test2"}, false},
            {"bucket3", "/home/aa", {"test1/test2"}, false}
    };
    BackupObjectInfosInCopy backupObjectInfosInCopy;
    BackupObjectInfo obj1;
    obj1.esn = "esn1";
    obj1.prefixInfo = std::move(prefix_esn1);
    backupObjectInfosInCopy.objectInfos.emplace_back(obj1);

    BackupObjectInfo obj2;
    obj2.esn = "esn2";
    obj2.prefixInfo = std::move(prefix_esn2);
    backupObjectInfosInCopy.objectInfos.emplace_back(obj2);

    StorageGeneralInfo storageGeneralInfo;
    EXPECT_EQ(backupjob.CheckAndGetObjectInfo("esn", storageGeneralInfo,
		backupObjectInfosInCopy), true);
    backupObjectInfosInCopy.objectInfos.pop_back();
    EXPECT_EQ(backupjob.CheckAndGetObjectInfo("esn", storageGeneralInfo,
		backupObjectInfosInCopy), false);
}
TEST_F(ObjectStorageMultiNodeBackupTest, LockStorageGeneralResources)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "XXXXX";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    MOCKER_CPP(&ShareResource::LockResource)
        .stubs()
        .will(ignoreReturnValue());
    MOCKER_CPP(&ShareResource::UnLockResource)
    .stubs()
    .will(ignoreReturnValue());
    EXPECT_EQ(backupjob.LockStorageGeneralResources("esn"), true);
    EXPECT_EQ(backupjob.UnLockStorageGeneralResources("esn"), true);
}

TEST_F(ObjectStorageMultiNodeBackupTest, CreateSubJobForMutiNodeBackup)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "XXXXX";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    backupjob.m_authInfo.storageType = std::to_string((int)Module::StorageType::HUAWEI);
    backupjob.m_dataFsPathMap["esn1"] = "/opt/dataBackup";
    MOCKER_CPP(&ObjectStorageBackupJob::ListBucketObjectsByDepth)
            .stubs()
            .will(invoke(ListBucketObjectsByDepthStub));
    MOCKER_CPP(&ObjectStorageBackupJob::WriteBackupObjectInfoToFile)
            .stubs()
            .will(returnValue(true));
    MOCKER_CPP(&JobService::ReportJobDetails)
            .stubs()
            .will(ignoreReturnValue());
    OBSPlugin::OBSProtectSubObject subObject{"bucket1", {"opt/aa"}};
    backupjob.m_protectedOBS.obsProtectSubObjectList.push_back(subObject);
    EXPECT_EQ(backupjob.CreateSubJobForMutiNodeBackup(), true);
}

TEST_F(ObjectStorageMultiNodeBackupTest, GetStorageGeneralResources)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "XXXXX";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    MOCKER_CPP(&ShareResource::QueryResource)
        .stubs()
        .will(ignoreReturnValue());
    StorageGeneralInfo generalInfo;
    EXPECT_EQ(backupjob.GetStorageGeneralResources("jobId", generalInfo), false);
}

TEST_F(ObjectStorageMultiNodeBackupTest, CreateStorageGeneralResources)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "XXXXX";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    MOCKER_CPP(&ObjectStorageBackupJob::GetStorageGeneralResources)
        .stubs()
        .will(returnValue(true))
        .then(returnValue(false));
    MOCKER_CPP(&ShareResource::CreateResource)
            .stubs()
            .will(ignoreReturnValue());
    StorageGeneralInfo generalInfo;
    EXPECT_EQ(backupjob.CreateStorageGeneralResources("jobId", generalInfo), true);
    EXPECT_EQ(backupjob.CreateStorageGeneralResources("jobId", generalInfo), true);
}


TEST_F(ObjectStorageMultiNodeBackupTest, IsProtectedObjectsChanged)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "XXXXX";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();

    ObjectStorageLastCopyDetails curObj;
    ObjectStorageLastCopyDetails preObj;


    OBSPlugin::OBSProtectSubObject object1;
    object1.bucketName = "bucket1";
    object1.prefixs.emplace_back("prefix1");
    backupjob.m_prevBackupRecord.m_obsProtectSubObjectList.emplace_back(object1);
    backupjob.m_protectedOBS.obsProtectSubObjectList.emplace_back(object1);

    EXPECT_EQ(backupjob.IsProtectedObjectsChanged(), false);
}

TEST_F(ObjectStorageMultiNodeBackupTest, IsProtectedObjectsChanged1)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "XXXXX";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();

    ObjectStorageLastCopyDetails curObj;
    ObjectStorageLastCopyDetails preObj;

    OBSPlugin::OBSProtectSubObject object1;
    object1.bucketName = "bucket1";
    object1.prefixs.emplace_back("prefix1");
    backupjob.m_prevBackupRecord.m_obsProtectSubObjectList.emplace_back(object1);

    OBSPlugin::OBSProtectSubObject object2;
    object2.bucketName = "bucket2";
    object2.prefixs.emplace_back("prefix1");
    backupjob.m_protectedOBS.obsProtectSubObjectList.emplace_back(object1);
    backupjob.m_protectedOBS.obsProtectSubObjectList.emplace_back(object2);
    EXPECT_EQ(backupjob.IsProtectedObjectsChanged(), true);
    backupjob.m_protectedOBS.obsProtectSubObjectList.erase(
        backupjob.m_protectedOBS.obsProtectSubObjectList.begin());
    EXPECT_EQ(backupjob.IsProtectedObjectsChanged(), true);
}

TEST_F(ObjectStorageMultiNodeBackupTest, CheckIsExistEsn)
{
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "XXXXX";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    BackupObjectInfo obj1;
    obj1.esn = "esn1";
    std::vector<BackupObjectInfo> objectInfos;
    objectInfos.emplace_back(obj1);
    EXPECT_EQ(backupjob.CheckIsExistEsn("esn1", objectInfos), true);
    EXPECT_EQ(backupjob.CheckIsExistEsn("esn2", objectInfos), false);
}

TEST_F(ObjectStorageMultiNodeBackupTest, SwitchStorageForMutiNodeBackup)
{
    MOCKER_CPP(&JobService::ReportJobDetails)
            .stubs()
            .will(ignoreReturnValue());
    MOCKER_CPP(&OBSPlugin::ObjectStorageBackupJob::LockStorageGeneralResources)
            .stubs()
            .will(returnValue(false));
    OBSPlugin::ObjectStorageBackupJob backupjob;
    auto info = std::make_shared<JobCommonInfo>();
    auto data = std::make_shared<AppProtect::BackupJob>();
    data->copy.id = "123";
    data->jobParam.backupType = AppProtect::BackupJobType::FULL_BACKUP;
    info->SetJobInfo(data);
    backupjob.SetJobInfo(info);
    backupjob.GetBackupJobInfo();
    backupjob.m_protectedOBS.advParms.m_continueOnFailedSwitch = "false";
    ObjectStorageBackupSubJob backupSubJob;
    EXPECT_EQ(backupjob.SwitchStorageForMutiNodeBackup(backupSubJob), Module::FAILED);
    backupjob.m_protectedOBS.advParms.m_continueOnFailedSwitch = "true";
    EXPECT_EQ(backupjob.SwitchStorageForMutiNodeBackup(backupSubJob), Module::FAILED);
}